package sf.core.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import sf.core.common.AdminStatus;
import sf.core.common.MessageStatus;
import sf.core.entity.TfMessage;
import sf.core.entity.TuAdmin;
import sf.core.entity.TuDeviceToken;
import sf.core.mapper.TfMessageMapper;
import sf.core.mapper.TuAdminMapper;
import sf.core.mapper.TuDeviceTokenMapper;
import sf.core.service.IPush;
import sf.core.service.PushService;

@Service
public class PushServiceImpl implements PushService {

	@Resource
	private TuAdminMapper adminMapper;

	@Resource
	private TfMessageMapper messageMapper;

	@Resource
	private TuDeviceTokenMapper deviceTokenMapper;

	@Resource
	private IPush jPush;

	public static final int UMENG = 1;

	public static final int JPUSH = 2;

	public static final int INVALID = -1;

	public static int UMENG_TOKEN_LENGTH_IOS = 64;

	public static int UMENG_TOKEN_LENGTH_ANDROID = 44;

	public static int JPUSH_TOKEN_LENGTH = 11;

	private Logger logger = LoggerFactory.getLogger(PushServiceImpl.class);

	@Override
	public void sendWelcomeMessage(int userType, int xid, String message) {

		TuAdmin query = new TuAdmin();
		query.setEmail(AdminStatus.EMAIL_SYSTEM);
		TuAdmin admin = adminMapper.selectOne(query);
		insertMessage(MessageStatus.TYPE_ADMIN, admin.getId(), userType, xid, message);

	}

	@Override
	public void sendSysMessage(int toType, int toId, String message, boolean needPush) {
		logger.debug("sendSysMessage , toType = " + toType + " , toId = " + toId + " , message = " + message);
		TuAdmin query = new TuAdmin();
		query.setEmail(AdminStatus.EMAIL_SYSTEM);
		TuAdmin admin = adminMapper.selectOne(query);
		insertSysMessage(MessageStatus.TYPE_ADMIN, admin.getId(), toType, toId, message);
		if (needPush) {
			checkAndSend(toType, toId, message);
		}
	}

	@Override
	public void sendUserMessage(int from_type, int from_id, int to_type, int to_id, String message, int entityType,
			int entityId, boolean needPush) {
		logger.debug("sendUserMessage , from_type = " + from_type + "from_id = " + from_id + "toType = " + to_type
				+ " , toId = " + to_id + " , message = " + message + " , entityType = " + entityType + " , entityId = "
				+ entityId);
		insertUserMessage(from_type, from_id, to_type, to_id, message, entityType, entityId);
		if (needPush) {
			checkAndSend(to_type, to_id, message);
		}
	}

	@Override
	public void saveDeviceToken(Integer type, int xid, String token) {
		if (token == null) {
			token = "";
		}
		TuDeviceToken deviceToken = queryDeviceToken(type, xid);
		if (deviceToken == null) {
			return;
		}
		if (StringUtils.isEmpty(deviceToken.getDevicetoken())) {
			deviceToken.setDevicetoken(token);
			deviceTokenMapper.insertSelective(deviceToken);
		} else {
			deviceToken.setDevicetoken(token);
			deviceTokenMapper.updateByPrimaryKeySelective(deviceToken);
		}

	}

	public TuDeviceToken queryDeviceToken(Integer userType, Integer xid) {
		TuDeviceToken tuDeviceToken = new TuDeviceToken();
		tuDeviceToken.setType(userType.byteValue());
		tuDeviceToken.setXid(xid);
		TuDeviceToken deviceToken = deviceTokenMapper.selectOne(tuDeviceToken);
		return deviceToken;
	}

	@Override
	public String retrieveDeviceToken(int userType, int xid) {
		String token = null;
		TuDeviceToken deviceToken = queryDeviceToken(userType, xid);
		if (deviceToken != null) {
			token = deviceToken.getDevicetoken();
		}
		return token;
	}

	@Override
	public void sendFeedbackMessage(int userType, int xid, String message) {

		TuAdmin query = new TuAdmin();
		query.setEmail(AdminStatus.EMAIL_SYSTEM);
		TuAdmin admin = adminMapper.selectOne(query);
		insertMessage(MessageStatus.TYPE_ADMIN, admin.getId(), userType, xid, message);
	}

	@Override
	public void sendTradeMessage(int userType, int xid, String message) {

		TuAdmin query = new TuAdmin();
		query.setEmail(AdminStatus.EMAIL_PAYMENT);
		TuAdmin admin = adminMapper.selectOne(query);
		sendUnicastMessage(MessageStatus.TYPE_ADMIN, admin.getId(), userType, xid, message, true);
	}

	@Override
	public void sendBroadcastMessage(int userType, String message) {

		TuAdmin query = new TuAdmin();
		query.setEmail(AdminStatus.EMAIL_SYSTEM);
		TuAdmin admin = adminMapper.selectOne(query);
		insertMessage(MessageStatus.TYPE_ADMIN, admin.getId(), userType, 0, message);
		try {
			broadcast(userType, message);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	@Override
	public void sendUnicastMessage(int fromType, int fromId, int toType, int toId, String message, boolean needPush) {

		insertMessage(fromType, fromId, toType, toId, message);

		if (needPush) {
			checkAndSend(toType, toId, message);
		}

	}

	@Override
	public void sendGroupcastMessage(int fromType, int fromId, int toType, List<Integer> toIds, String message,
			boolean needPush) {
		insertMessages(fromType, fromId, toType, toIds, message);
		if (!needPush) {
			return;
		}
		List<String> tokens = new ArrayList<String>();
		TuDeviceToken query = new TuDeviceToken();
		for (int i = 0; i < toIds.size(); i++) {
			query.setXid(toIds.get(i));
			TuDeviceToken token = deviceTokenMapper.selectOne(query);
			if (token != null) {
				tokens.add(token.getDevicetoken());
			}
		}

		try {
			groupcast(tokens, toType, message);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}

	}

	@Override
	public void unicast(String deviceToken, int userType, String message) throws Exception {
		jPush.unicast(deviceToken, userType, message);
	}

	@Override
	public void broadcast(int userType, String message) throws Exception {
		jPush.broadcast(userType, message);
	}

	@Override
	public void groupcast(List<String> deviceTokens, int userType, String message) throws Exception {
		List<String> jpushDecieToken = new ArrayList<>();
		for (String deviceToken : deviceTokens) {
			jpushDecieToken.add(deviceToken);
		}
		jPush.groupcast(jpushDecieToken, userType, message);
	}

	private void checkAndSend(int userType, int xid, String message) {
		String token = retrieveDeviceToken(userType, xid);
		if (null != token) {
			try {
				logger.error(token + ":" + message);
				unicast(token, userType, message);
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
	}

	public void addMessage(Integer fromType, Integer fromId, Integer toType, Integer toId, String text,
			Integer messageType, Integer entityType, Integer entityId) {
		TfMessage message = new TfMessage();
		message.setFromtype(fromType.byteValue());
		message.setFromid(fromId);
		message.setTotype(toType.byteValue());
		message.setToid(toId);
		message.setText(text);
		message.setType(entityType);
		message.setXid(entityId);
		message.setMessagetype(messageType);
		messageMapper.insertSelective(message);
	}

	private void insertMessage(Integer fromType, Integer fromId, Integer toType, Integer toId, String text) {
		addMessage(fromType, fromId, toType, toId, text, null, null, null);
	}

	private void insertUserMessage(int fromType, int fromId, int toType, int toId, String message, int entityType,
			int entityId) {
		addMessage(fromType, fromId, toType, toId, message, MessageStatus.MESSAGE_TYPE_USER, null, null);
	}

	private void insertSysMessage(int fromType, int fromId, int toType, int toId, String message) {
		addMessage(fromType, fromId, toType, toId, message, MessageStatus.MESSAGE_TYPE_SYS, 0, 0);
	}

	private void insertMessages(int fromType, int fromId, int toType, List<Integer> toIds, String text) {
		for (int i = 0; i < toIds.size(); i++) {
			addMessage(fromType, fromId, toType, toIds.get(i), text, null, null, null);
		}
	}

}
